
import numpy as np
import pandas as pd
from sqlalchemy import create_engine
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from mpl_toolkits.mplot3d.axes3d import Axes3D # 3D引擎
# 1.读取数据
data = pd.read_excel('C:/Users/Administrator/Desktop/车贷违约预测.xlsx')

# 2.异常值处理
print(data.duplicated().sum())
print(data['是否违约'].value_counts() )
# 缺失值处理
# for i in data.columns:
# print(data.isnull().sum())
# print(data.shape)
data = data.dropna(axis=0)
# print(data.shape)
# 4.衍生字段
def yansheng():
    data["贷款有效次数占比"]=data['主账户有效贷款次数']/data['主账户贷款次数']
    data["共计还完贷款月数"]=data["已发货款"]/data["每月还款总额"]
    print(data["已发货款"].dtype)
    print(data["每月还款总额"].dtype)
    data['主次账号共计有效贷款次数']=data['主账户有效贷款次数']+data['次账户有效贷款次数']
    data['主次账号共计贷款次数']=data['主账户贷款次数']+data['次账户贷款次数']
    data['主次账号共计有效贷款次数占比']=data['主次账号共计有效贷款次数']/data['主次账号共计贷款次数']
    def xx(val):
        if val ==None:
            return 0
    print(data["贷款有效次数占比"].fillna("0")) #处理分母为0
    print(data["共计还完贷款月数"].fillna(0))#处理分母为0
    print(data['主次账号共计有效贷款次数'])
    print(data['主次账号共计贷款次数'])
    print(data['主次账号共计有效贷款次数占比'].fillna(0))

# 5.失衡数据判断并处理
def deal_shiheng():
    for i in data.columns:
        data[i] = data[i].astype("str")
    print(data.describe(include="all"))

    from imblearn.under_sampling import NearMiss  # KNN
    ee = NearMiss(version=1)
    X_resampled, y_resampled = ee.fit_sample(data.loc[:,
                                             ["user_id"]], data["次账户贷款次数"])
    user_merchant = pd.concat([X_resampled, y_resampled], axis=1)
    user_merchant.head()


# 多个备选模型比较
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score,roc_auc_score,recall_score,precision_score
from sklearn.tree import DecisionTreeClassifier
from sklearn.svm import SVC
from sklearn.ensemble import AdaBoostClassifier, GradientBoostingClassifier
from xgboost.sklearn import XGBClassifier
import warnings
warnings.filterwarnings('ignore')

# 封装模型调⽤ 评估函数
def train_model(X_train, y_train, X_test, y_test,model,model_name):
    print('训练{}'.format(model_name))
    clf=model
    clf.fit(X_train, y_train.values.ravel())
    #验证模型
    print('训练准确率：{:.4f}'.format(clf.score(X_train, y_train)))
    predict=clf.predict(X_test)
    score = clf.score(X_test, y_test)
    precision=precision_score(y_test,predict)
    recall=recall_score(y_test,predict)
    print('测试准确率：{:.4f}'.format(score))
    print('测试精确率：{:.4f}'.format(precision))
    print('测试召回率：{:.4f}'.format(recall))
    return model_name,score,precision,recall




#从模型中备选模型中选择⼀个最有模型
model_name_param_dict = { 'LR': (LogisticRegression(penalty ="l2")),
'DT':(DecisionTreeClassifier(max_depth=10,min_samples_split=10)),
'AdaBoost': (AdaBoostClassifier()),
'GBDT': (GradientBoostingClassifier()),
# 'RF': (RandomForestClassifier()),
'XGBoost':(XGBClassifier())
}
result_df = pd.DataFrame(columns=['Accuracy(%)','precision(%)','recall(%)','model'],
index=list(model_name_param_dict.keys()))
# print(result_df)
Y=data.pop('是否违约')
X = data
X_train,X_test,y_train,y_test = train_test_split(X,Y,test_size=0.3,random_state=6)
for model_name, model in model_name_param_dict.items():
    clf, acc,pre,recall = train_model(X_train, y_train,X_test, y_test,model,model_name)
    # model_dict
    result_df.loc[model_name, 'Accuracy (%)'] = acc
    result_df.loc[model_name, 'precision(%)'] = pre
    result_df.loc[model_name, 'recall(%)'] = recall
    result_df.loc[model_name, 'model'] = clf

print(result_df)
# 7.利用网格搜索调优
from sklearn.model_selection import GridSearchCV #网格搜索
p = {
    # 'C':list(np.linspace(0.05,1,19)),
    'solver':['liblinear','sag','newton-cg','lbfgs']
}

model = LogisticRegression(penalty='l2',max_iter=10000)

GS = GridSearchCV(model,p,cv=5)
GS.fit(X_train,y_train)
print(GS.best_score_)
print(GS.best_params_)
model = LogisticRegression(penalty='l2',
           max_iter=10000,
           # C=GS.best_params_['C'],
           solver=GS.best_params_['solver'])
model.fit(X_train,y_train)
print(model.score(X_train,y_train),model.score(X_test,y_test))

# 8.优质模型保存
import os
result_df.to_csv(os.path.join('model_comparison.csv'))